using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;

namespace PerformanceDude.MSBuildProfiler
{
    [Serializable]
    public abstract class Item
    {
        protected Item(string itemName, string helpKeyword, string message, string senderName, int threadId,
                    DateTime timestamp)
        {
            ItemName = itemName;
            HelpKeyword = helpKeyword;
            Message = message;
            SenderName = senderName;
            ThreadId = threadId;
            Timestamp = timestamp;
            StartTime = DateTime.UtcNow.Ticks;
            Children = new List<Item>();
        }

        public string ItemName;
        public long StartTime;
        public long FinishTime;

        public long Duration
        {
            get { return FinishTime - StartTime; }
        }

        public string HelpKeyword;
        public string Message;
        public string SenderName;
        public int ThreadId;
        public DateTime Timestamp;
        public IList<Item> Children;

        public bool IsConsuming()
        {
            var sum = Children.Aggregate(Duration, (current, item) => current - item.Duration);
            return sum > 0;
        }
    }

    [Serializable]
    public class Build : Item
    {
        public Build(string buildName, string helpKeyword, string message, string senderName, int threadId,
                     DateTime timestamp)
            : base(buildName, helpKeyword, message, senderName, threadId, timestamp)
        {
        }
    }

    [Serializable]
    public class Project : Item
    {
        public string ProjectFile;
        public IDictionary<object, object> Properties;
        public string TargetNames;

        public Project(string projectName, string projectFile, IEnumerable properties, string targetNames,
                       string helpKeyword, string message, string senderName, int threadId, DateTime timestamp)
            : base(projectName, helpKeyword, message, senderName, threadId, timestamp)
        {
            Properties = new Dictionary<object, object>();
            foreach (DictionaryEntry o in properties)
            {
                Properties.Add(o.Key, o.Value);
            }
            ProjectFile = projectFile;
            TargetNames = targetNames;
        }
    }

    [Serializable]
    public class Target : Item
    {
        public string ProjectFile;
        public string TargetFile;
        public string TargetName;

        public Target(string name, string projectFile, string targetFile, string targetName, string helpKeyword,
                      string message, string senderName, int threadId, DateTime timestamp)
            : base(name, helpKeyword, message, senderName, threadId, timestamp)
        {
            ProjectFile = projectFile;
            TargetFile = targetFile;
            TargetName = targetName;
        }
    }

    [Serializable]
    public class Task : Item
    {
        public string ProjectFile;
        public string TaskFile;
        public string TaskName;

        public Task(string name, string projectFile, string taskFile, string taskName, string helpKeyword,
                    string message, string senderName, int threadId, DateTime timestamp)
            : base(name, helpKeyword, message, senderName, threadId, timestamp)
        {
            ProjectFile = projectFile;
            TaskFile = taskFile;
            TaskName = taskName;
        }
    }
}